package com.lyf.scm.plan.domain.service.impl;

import com.github.pagehelper.PageInfo;
import com.lyf.scm.common.enums.SkuUnitTypeEnum;
import com.lyf.scm.plan.api.dto.BaseAreaInfoDTO;
import com.lyf.scm.plan.api.dto.BaseSkuInfoDTO;
import com.lyf.scm.plan.api.dto.StoreInfoDTO;
import com.lyf.scm.plan.api.dto.UnitRateQueryDTO;
import com.lyf.scm.plan.domain.remote.basedata.dto.*;
import com.lyf.scm.plan.domain.remote.basedata.facade.BaseDataFacade;
import com.lyf.scm.plan.domain.remote.item.dto.CategorySimpleDTO;
import com.lyf.scm.plan.domain.remote.item.dto.SkuInfoDTO;
import com.lyf.scm.plan.domain.remote.item.dto.SkuPriceDTO;
import com.lyf.scm.plan.domain.remote.item.dto.SkuUnitDTO;
import com.lyf.scm.plan.domain.remote.item.facade.ItemCoreFacade;
import com.lyf.scm.plan.domain.remote.stock.facade.StockCoreFacade;
import com.lyf.scm.plan.domain.service.RedisCacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.lyf.scm.common.util.BatchHandlerUtil.splitTo;


/**
 * 大数据redis缓存
 *
 * @author wangchlei
 * @date 2020/09/20
 */
@Slf4j
@Service
public class RedisCacheServiceImpl implements RedisCacheService {
    public static final String PLAN_STORE_PREFIX = "PLAN_STORE::";
    public static final String CHANNEL_LIST = "SALES_PLAN_REDIS_KEY_CHANNEL_LIST";
    public static final String PLAN_PRICE_PREFIX = "PLAN_PRICE::";
    public static final String PLAN_CATEGORY_PREFIX = "PLAN_CATEGORY::";
    public static final String PLAN_UNIT_PREFIX = "PLAN_UNIT::";
    public static final String PLAN_AREA_PREFIX = "PLAN_AREA::";
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private ItemCoreFacade itemCoreFacade;
    @Resource
    private BaseDataFacade baseDataFacade;
    @Resource
    private StockCoreFacade stockCoreFacade;

    /**
     * 查询所有渠道的信息
     *
     * @param
     * @return {@link Map<ChannelDTO>}
     **/
    @Override
    @Cacheable(value = "SCM_PLAN_CHANNEL", key = "'info'", sync = true)
    public Map<String, ChannelDTO> getAllChannelInfo() {
        log.warn("\n【获取渠道信息】：执行获取所有渠道方法,未命中缓存");
        List<ChannelDTO> channels = baseDataFacade.getChannelByLevel(1);
        if (CollectionUtils.isEmpty(channels)) {
            return new HashMap<>(1);
        }
        return channels.stream().collect(Collectors.toMap(ChannelDTO::getChannel, item -> item));
    }

    @Override
    @Cacheable(value = "SCM_PLAN_DELIVER", key = "'info'", sync = true)
    public Map<String, StoreDTO> getDeliverWarehouse() {
        log.warn("\n【获取发货仓库信息】：执行获取所有发货仓库方法,未命中缓存");
        List<StoreDTO> storeDTOs = stockCoreFacade.queryFactoryByRwType(16);
        if (CollectionUtils.isEmpty(storeDTOs)) {
            return new HashMap<>(1);
        }
        return storeDTOs.stream().collect(Collectors.toMap(StoreDTO::getCode, item -> item));
    }

    /**
     * 批量根据门店code查询门店对应的省市区
     *
     * @param
     * @return {@link Map<ChannelDTO>}
     **/
    @Override
    public Map<String, StoreDTO> getStoreInfoByCodes(List<String> codes) {
        if (CollectionUtils.isEmpty(codes)) {
            return new HashMap<>(1);
        }
        List<String> distinctCodes = codes.stream().distinct().collect(Collectors.toList());
        //遍历code获取redis中的值，同时统计不存在的值
        ValueOperations<String, StoreDTO> valueOperations = redisTemplate.opsForValue();
        List<StoreDTO> result = new ArrayList<>();
        List<String> tmp = new ArrayList<>();
        StoreDTO item;
        for (String code : distinctCodes) {
            item = valueOperations.get(PLAN_STORE_PREFIX + code);
            if (item == null) {
                log.warn("\n【获取门店 " + code + " 信息】：未命中缓存");
                tmp.add(code);
            } else {
                result.add(item);
            }
        }
        //获取位录入缓存的门店信息，加入缓存
        if (!CollectionUtils.isEmpty(tmp)) {
            List<StoreDTO> storeDTOS = baseDataFacade.selectStoreListByCodes(tmp);
            result.addAll(storeDTOS);
            for (StoreDTO element : storeDTOS) {
                valueOperations.set(PLAN_STORE_PREFIX + element.getCode(), element, 3, TimeUnit.HOURS);
            }
        }
        return result.stream().collect(Collectors.toMap(StoreDTO::getCode, element -> element));
    }

    /**
     * 批量根据sku+unit
     *
     * @param
     * @return {@link Map<ChannelDTO>}
     **/
    @Override
    public Map<String, BigDecimal> getSkuAveragePrice(List<SkuPriceDTO> skuPriceDTOs) {
        if (CollectionUtils.isEmpty(skuPriceDTOs)) {
            return new HashMap<>(1);
        }
        List<SkuPriceDTO> distinctList = skuPriceDTOs.stream().distinct().collect(Collectors.toList());
        Map<String, BigDecimal> result = new HashMap<>(1);
        try {
            // 先找到所有100的渠道组
            List<ChannelDTO> channelList = (List<ChannelDTO>) redisTemplate.opsForValue().get(CHANNEL_LIST);
            ValueOperations<String, BigDecimal> valueOperations = redisTemplate.opsForValue();
            if (channelList == null) {
                ChannelInfoDTO channelQuery = new ChannelInfoDTO();
                channelQuery.setChannelType("100");
                channelQuery.setSaleUnitType(1);
                PageInfo<ChannelDTO> channelPage = baseDataFacade.getChannelPage(channelQuery);
                if (channelPage == null || channelPage.getList() == null || channelPage.getList().size() == 0) {
                    return result;
                }
                channelList = channelPage.getList();
                redisTemplate.opsForValue().set(CHANNEL_LIST, channelList, Duration.ofMinutes(15));
            }
            // 把sku和渠道组合查询
            List<SkuPriceDTO> skuPriceQuery = new ArrayList<>();
            BigDecimal tmpPrice;
            String tmpSku;
            String tmpUnit;
            String tmpChannel;
            for (SkuPriceDTO skuPriceDTO : distinctList) {
                for (ChannelDTO channelDTO : channelList) {
                    tmpSku = skuPriceDTO.getSkuCode();
                    tmpUnit = skuPriceDTO.getSaleUnitCode();
                    tmpChannel = channelDTO.getChannelCode();
                    tmpPrice = valueOperations.get(PLAN_PRICE_PREFIX + tmpSku + tmpUnit);
                    if (tmpPrice == null) {
                        log.warn("\n【获取价格 " + tmpSku + "," + tmpUnit + " 信息】：未命中缓存");
                        SkuPriceDTO dto = new SkuPriceDTO();
                        dto.setSkuCode(tmpSku);
                        dto.setSaleUnitCode(tmpUnit);
                        dto.setChannelCode(tmpChannel);
                        skuPriceQuery.add(dto);
                        continue;
                    }
                    result.put(tmpSku + tmpUnit, tmpPrice);
                }
            }
            if (CollectionUtils.isNotEmpty(skuPriceQuery)) {
                List<SkuPriceDTO> skuPriceDTOList = new ArrayList<>();
                List<List<SkuPriceDTO>> batch = splitTo(skuPriceQuery, 100);
                for (List<SkuPriceDTO> item : batch) {
                    skuPriceDTOList.addAll(itemCoreFacade.getSkuPrice(item));
                }
                if (skuPriceDTOList == null || skuPriceDTOList.size() == 0) {
                    return result;
                }
                // 按sku合并
                String skuInfo;
                Map<String, List<SkuPriceDTO>> collect = new HashMap<>();
                for (SkuPriceDTO skuPriceDTO : skuPriceDTOList) {
                    if (skuPriceDTO.getSalePrice() == null) {
                        continue;
                    }
                    skuInfo = skuPriceDTO.getSkuCode() + skuPriceDTO.getSaleUnitCode();
                    List<SkuPriceDTO> subList = collect.get(skuInfo);
                    if (subList == null) {
                        subList = new ArrayList<>();
                        collect.put(skuInfo, subList);
                    }
                    subList.add(skuPriceDTO);
                }
                // 把价格求平均值
                for (Map.Entry<String, List<SkuPriceDTO>> entry : collect.entrySet()) {
                    skuInfo = entry.getKey();
                    List<SkuPriceDTO> value = entry.getValue();
                    if (value == null || value.size() == 0) {
                        continue;
                    }
                    BigDecimal sum = BigDecimal.ZERO;
                    for (SkuPriceDTO skuPriceDTO : value) {
                        sum = sum.add(skuPriceDTO.getSalePrice());
                    }
                    tmpPrice = sum.divide(BigDecimal.valueOf(value.size()), 2, BigDecimal.ROUND_HALF_UP);
                    result.put(skuInfo, tmpPrice);
                    valueOperations.set(PLAN_PRICE_PREFIX + skuInfo, tmpPrice, 3, TimeUnit.HOURS);
                }
            }
            return result;
        } catch (Exception e) {
            log.error("取价格异常", e);
        }
        return result;
    }

    /**
     * 根据skucodes获取sku相关的品类信息
     *
     * @param skuCodes
     * @return void
     **/
    @Override
    public Map<String, BaseSkuInfoDTO> getCategoryInfoBySkuCodes(List<String> skuCodes) {
        if (CollectionUtils.isEmpty(skuCodes)) {
            return new HashMap<>(1);
        }
        List<String> distinctSkuCodes = skuCodes.stream().distinct().collect(Collectors.toList());
        Map<String, BaseSkuInfoDTO> map = new HashMap<>();
        ValueOperations<String, BaseSkuInfoDTO> valueOperations = redisTemplate.opsForValue();
        BaseSkuInfoDTO tmp;
        List<String> notExsit = new ArrayList<>();
        for (String code : distinctSkuCodes) {
            tmp = valueOperations.get(PLAN_CATEGORY_PREFIX + code);
            if (tmp != null) {
                map.put(code, tmp);
                continue;
            }
            notExsit.add(code);
        }
        if (!CollectionUtils.isEmpty(notExsit)) {
            List<SkuInfoDTO> skuInfoDTOS = itemCoreFacade.skuListBySkuCodes(notExsit);
            Map<String, SkuInfoDTO> skuCodeName = this.getSkuInfo(skuInfoDTOS);
            Map<Integer, List<CategorySimpleDTO>> categoryInfo = this.getCategoryInfo(skuInfoDTOS);
            BaseSkuInfoDTO baseSkuInfoDTO;
            SkuInfoDTO skuInfoDTO;
            List<CategorySimpleDTO> categorySimpleDTOS;
            for (String item : notExsit) {
                baseSkuInfoDTO = new BaseSkuInfoDTO();
                baseSkuInfoDTO.setSkuCode(item);
                if (skuCodeName.get(item) != null) {
                    skuInfoDTO = skuCodeName.get(item);
                    baseSkuInfoDTO.setSkuName(skuInfoDTO.getName());
                    categorySimpleDTOS = categoryInfo.get(skuInfoDTO.getCategoryId());
                    if (!CollectionUtils.isEmpty(categorySimpleDTOS)) {
                        //排序 按照 大品类，中品类，小品类
                        categorySimpleDTOS.sort(Comparator.comparingInt(CategorySimpleDTO::getCategoryLevel));
                        BaseSkuInfoDTO finalBaseSkuInfoDTO = baseSkuInfoDTO;
                        categorySimpleDTOS.forEach(subItem -> this.setGeneralCategoryValue(subItem, finalBaseSkuInfoDTO));
                    }
                }
                map.put(item, baseSkuInfoDTO);
                valueOperations.set(PLAN_CATEGORY_PREFIX + item, baseSkuInfoDTO, 3, TimeUnit.HOURS);
            }
        }
        return map;
    }

    /**
     * 获取单位转换率(一次只能查源单位到目标单位相同的组合,不转换基础单位到基础单位的组合)
     *
     * @param unitRateQueryDTOs
     * @return {@link Map<SkuUnitDTO>}
     **/
    @Override
    public Map<String, SkuUnitDTO> getUnitConversionRatio(List<UnitRateQueryDTO> unitRateQueryDTOs) {
        if (CollectionUtils.isEmpty(unitRateQueryDTOs)) {
            return new HashMap<>(1);
        }
        List<UnitRateQueryDTO> distinctCodes = unitRateQueryDTOs.stream().distinct().collect(Collectors.toList());
        //遍历code获取redis中的值，同时统计不存在的值
        ValueOperations<String, SkuUnitDTO> valueOperations = redisTemplate.opsForValue();
        Map<String, SkuUnitDTO> result = new HashMap<>();
        List<UnitRateQueryDTO> tmp = new ArrayList<>();
        String tmpSuffix;
        SkuUnitDTO rate;
        for (UnitRateQueryDTO element : distinctCodes) {
            tmpSuffix = element.getSkuCode() + element.getFromUnitType() + element.getToUnitType();
            rate = valueOperations.get(PLAN_UNIT_PREFIX + tmpSuffix);
            if (rate == null) {
                log.warn("\n【获取单位转换率 " + tmpSuffix + " 信息】：未命中缓存");
                tmp.add(element);
            } else {
                result.put(tmpSuffix, rate);
            }
        }
        //获取位录入缓存的门店信息，加入缓存
        if (!CollectionUtils.isEmpty(tmp)) {
            List<String> skuCodes = tmp.stream().map(UnitRateQueryDTO::getSkuCode).collect(Collectors.toList());
            Long fromUnitType = tmp.get(0).getFromUnitType();
            Long toUnitType = tmp.get(0).getToUnitType();
            if (SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(fromUnitType) && SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(toUnitType)) {
                return null;
            }
            SkuUnitDTO skuUnitDTO;
            List<SkuUnitDTO> fromSkuUnitDTOS;
            List<SkuUnitDTO> toSkuUnitDTOS;
            if (!SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(fromUnitType) && SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(toUnitType)) {
                fromSkuUnitDTOS = itemCoreFacade.getConversionRatio(skuCodes, fromUnitType);
                toSkuUnitDTOS = itemCoreFacade.getConversionRatio(skuCodes, toUnitType);
                Map<String, Double> map = fromSkuUnitDTOS.stream().collect(Collectors.toMap(SkuUnitDTO::getSkuCode, SkuUnitDTO::getScale));
                Map<String, SkuUnitDTO> toMap = toSkuUnitDTOS.stream().collect(Collectors.toMap(SkuUnitDTO::getSkuCode, item -> item));
                for (String element : skuCodes) {
                    if (!map.containsKey(element) || !toMap.containsKey(element)) {
                        continue;
                    }
                    skuUnitDTO = new SkuUnitDTO();
                    skuUnitDTO.setScale(map.get(element));
                    skuUnitDTO.setUnitName(toMap.get(element).getUnitName());
                    skuUnitDTO.setUnitCode(toMap.get(element).getUnitCode());
                    valueOperations.set(PLAN_UNIT_PREFIX + element + fromUnitType + toUnitType, skuUnitDTO, 3, TimeUnit.HOURS);
                    result.put(element + fromUnitType + toUnitType, skuUnitDTO);
                }
            }
            if (SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(fromUnitType) && !SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(toUnitType)) {
                toSkuUnitDTOS = itemCoreFacade.getConversionRatio(skuCodes, toUnitType);
                Map<String, SkuUnitDTO> map = toSkuUnitDTOS.stream().collect(Collectors.toMap(SkuUnitDTO::getSkuCode, item -> item));
                for (String element : skuCodes) {
                    if (!map.containsKey(element)) {
                        continue;
                    }
                    skuUnitDTO = new SkuUnitDTO();
                    skuUnitDTO.setScale(1 / map.get(element).getScale());
                    skuUnitDTO.setUnitName(map.get(element).getUnitName());
                    skuUnitDTO.setUnitCode(map.get(element).getUnitCode());
                    valueOperations.set(PLAN_UNIT_PREFIX + element + fromUnitType + toUnitType, skuUnitDTO, 3, TimeUnit.HOURS);
                    result.put(element + fromUnitType + toUnitType, skuUnitDTO);
                }
            }
            if (!SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(fromUnitType) && !SkuUnitTypeEnum.BASIS_UNIT.getUnitType().equals(toUnitType)) {
                toSkuUnitDTOS = itemCoreFacade.getConversionRatio(skuCodes, toUnitType);
                fromSkuUnitDTOS = itemCoreFacade.getConversionRatio(skuCodes, fromUnitType);
                Map<String, SkuUnitDTO> toMap = toSkuUnitDTOS.stream().collect(Collectors.toMap(SkuUnitDTO::getSkuCode, item -> item));
                Map<String, Double> fromMap = fromSkuUnitDTOS.stream().collect(Collectors.toMap(SkuUnitDTO::getSkuCode, SkuUnitDTO::getScale));
                for (String element : skuCodes) {
                    if (!toMap.containsKey(element) || !fromMap.containsKey(element)) {
                        continue;
                    }
                    skuUnitDTO = new SkuUnitDTO();
                    skuUnitDTO.setScale(fromMap.get(element) * (1 / toMap.get(element).getScale()));
                    skuUnitDTO.setUnitName(toMap.get(element).getUnitName());
                    skuUnitDTO.setUnitCode(toMap.get(element).getUnitCode());
                    valueOperations.set(PLAN_UNIT_PREFIX + element + fromUnitType + toUnitType, skuUnitDTO, 3, TimeUnit.HOURS);
                    result.put(element + fromUnitType + toUnitType, skuUnitDTO);
                }
            }
        }
        return result;
    }

    @Override
    public Map<String, BaseAreaInfoDTO> getAreaInfo(List<String> codes, Integer type) {
        Map<String, BaseAreaInfoDTO> areaMap = new HashMap<>();
        if (type == null || CollectionUtils.isEmpty(codes)) {
            return areaMap;
        }
        //遍历code获取redis中的值，同时统计不存在的值
        ValueOperations<String, BaseAreaInfoDTO> valueOperations = redisTemplate.opsForValue();
        //省市区
        List<String> tmp = new ArrayList<>();
        BaseAreaInfoDTO item;
        for (String code : codes) {
            item = valueOperations.get(PLAN_AREA_PREFIX + code);
            if (item == null) {
                log.warn("\n【获取区域 " + code + " 信息】：未命中缓存");
                tmp.add(code);
            } else {
                areaMap.put(code, item);
            }
        }
        if (CollectionUtils.isNotEmpty(tmp)) {
            String tmpCode;
            String tmpName;
            BaseAreaInfoDTO baseAreaInfoDTO;
            if (type.equals(2)) {
                List<StoreDTO> storeDTOS = baseDataFacade.searchByCodeList(tmp);
                if (CollectionUtils.isEmpty(storeDTOS)) {
                    return areaMap;
                }
                for (StoreDTO element : storeDTOS) {
                    tmpName = element.getProvince() + "/" + element.getCity() + "/" + element.getCounty() + "/" + element.getCode();
                    tmpCode = element.getProvinceCode() + "/" + element.getCityCode() + "/" + element.getDistrictCode() + "/" + element.getCode();
                    baseAreaInfoDTO = new BaseAreaInfoDTO();
                    baseAreaInfoDTO.setAreaNameSplicing(tmpName);
                    baseAreaInfoDTO.setAreaCodeSplicing(tmpCode);
                    valueOperations.set(PLAN_AREA_PREFIX + element.getCode(), baseAreaInfoDTO, 3, TimeUnit.HOURS);
                    areaMap.put(element.getCode(), baseAreaInfoDTO);
                }
            }
            //区域
            if (type.equals(1)) {
                List<AreaLevelDTO> areaLevelDTOS = baseDataFacade.listRelationByArea(tmp);
                if (CollectionUtils.isEmpty(areaLevelDTOS)) {
                    return areaMap;
                }
                for (AreaLevelDTO element : areaLevelDTOS) {
                    baseAreaInfoDTO = new BaseAreaInfoDTO();
                    tmpName = element.getNameFullPath().replace("中国-", "").replace("-", "/");
                    tmpCode = element.getCodeFullPath().replace("100000-", "").replace("-", "/");
                    baseAreaInfoDTO.setAreaNameSplicing(tmpName);
                    baseAreaInfoDTO.setAreaCodeSplicing(tmpCode);
                    valueOperations.set(PLAN_AREA_PREFIX + element.getCode(), baseAreaInfoDTO, 3, TimeUnit.HOURS);
                    areaMap.put(element.getCode(), baseAreaInfoDTO);
                }
            }
        }
        return areaMap;
    }

    /**
     * 设置通用属性 设置品类
     *
     * @param subItem
     * @return void
     **/
    private void setGeneralCategoryValue(CategorySimpleDTO subItem, BaseSkuInfoDTO baseSkuInfoDTO) {
        Integer level = subItem.getCategoryLevel();
        switch (level) {
            case 2:
                baseSkuInfoDTO.setPriCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseSkuInfoDTO.setCategory(subItem.getCategoryName());
                break;
            case 3:
                baseSkuInfoDTO.setSecCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseSkuInfoDTO.setCategory(baseSkuInfoDTO.getCategory() + "/" + subItem.getCategoryName());
                break;
            case 4:
                baseSkuInfoDTO.setTerCategoryCode(String.valueOf(subItem.getCategoryCode()));
                baseSkuInfoDTO.setCategory(baseSkuInfoDTO.getCategory() + "/" + subItem.getCategoryName());
                break;
            default:
        }
    }

    /**
     * 根据skuInfo获取sku-map信息
     *
     * @param skuInfoDTOS
     * @return void
     **/
    private Map<String, SkuInfoDTO> getSkuInfo(List<SkuInfoDTO> skuInfoDTOS) {
        //根据skuCodes查询skuInfo
        Map<String, SkuInfoDTO> skuCodeName = new HashMap<>();
        if (!CollectionUtils.isEmpty(skuInfoDTOS)) {
            skuCodeName = skuInfoDTOS.stream().collect(Collectors.toMap(SkuInfoDTO::getSkuCode, item -> item));
        }
        return skuCodeName;
    }

    /**
     * 根据skuInfo获取sku品类信息
     *
     * @param skuInfoDTOS
     * @return void
     **/
    private Map<Integer, List<CategorySimpleDTO>> getCategoryInfo(List<SkuInfoDTO> skuInfoDTOS) {
        Map<Integer, List<CategorySimpleDTO>> categoryInfo = new HashMap<>();
        if (!CollectionUtils.isEmpty(skuInfoDTOS)) {
            List<CategorySimpleDTO> categorySimpleDTOS = itemCoreFacade.getAllCategoryByCategoryId(skuInfoDTOS.stream().map(SkuInfoDTO::getCategoryId).distinct().collect(Collectors.toList()));
            categoryInfo = categorySimpleDTOS.stream().collect(Collectors.toMap(CategorySimpleDTO::getId, CategorySimpleDTO::getParentCategoryDTOList));
        }
        return categoryInfo;
    }

    /**
     * 获取所有门店（优先从缓存中获取）
     *
     * @param
     * @return {@link List < StoreDTO >}
     **/
    @Cacheable(value = "PLAN_STORE_CACHE", key = "'stores'", sync = true)
    public Map<String, StoreInfoDTO> getAllStores() {
        log.warn("\n【大数据处理Job】：执行获取所有门店方法,未命中缓存");
        return this.getStoresInfo();
    }

    /**
     * 获取所有直营门店（优先从缓存中获取）
     *
     * @param
     * @return {@link List < StoreDTO >}
     **/
    @Cacheable(value = "PLAN_DIRECT_STORE_CACHE", key = "'stores'", sync = true)
    public Map<String, StoreInfoDTO> getDirectStores() {
        log.warn("\n【大数据处理Job】：执行获取所有直营门店方法,未命中缓存");
        return this.getDirectStoresInfo();
    }

    /**
     * 定时更新门店缓存
     *
     * @param
     * @return void
     **/
    @CachePut(value = "PLAN_STORE_CACHE", key = "'stores'")
    public Map<String, StoreInfoDTO> updateStores() {
        log.info("\n【大数据处理Job】：执行获取所有门店方法,开始更新缓存");
        return this.getStoresInfo();
    }

    /**
     * 定时更新门店缓存
     *
     * @param
     * @return void
     **/
    @CachePut(value = "PLAN_DIRECT_STORE_CACHE", key = "'stores'")
    public Map<String, StoreInfoDTO> updateDirectStores() {
        log.info("\n【大数据处理Job】：执行获取所有直营门店方法,开始更新缓存");
        return this.getDirectStoresInfo();
    }


    /**
     * 清空门店缓存
     *
     * @param
     * @return void
     **/
    @Override
    @CacheEvict(value = "PLAN_STORE_CACHE", allEntries = true, beforeInvocation = true)
    public void deleteStores() {
        log.info("\n【清空缓存】：已清空门店缓存");
    }

    /**
     * 清空门店缓存
     *
     * @param
     * @return void
     **/
    @Override
    @CacheEvict(value = "PLAN_DIRECT_STORE_CACHE", allEntries = true, beforeInvocation = true)
    public void deleteDirectStores() {
        log.info("\n【清空缓存】：已清空直营门店缓存");
    }


    private Map<String, StoreInfoDTO> getStoresInfo() {
        List<StoreInfoDTO> storeDTO = baseDataFacade.listStoreInfo(new StoreDTO()).getList();
        return this.getResult(storeDTO);
    }


    private Map<String, StoreInfoDTO> getDirectStoresInfo() {
        Map<String, StoreInfoDTO> allStores = this.getStoresInfo();
        List<StoreInfoDTO> directStores = baseDataFacade.listDirectStores();
        Map<String, StoreInfoDTO> result = new HashMap<>();
        directStores.forEach(item -> {
            if (allStores.containsKey(item.getCode())) {
                result.put(item.getCode(), allStores.get(item.getCode()));
            }
        });
        return result;
    }

    private Map<String, StoreInfoDTO> getResult(List<StoreInfoDTO> storeDTO) {
        List<AreaDTO> provinceAreaDTOS = baseDataFacade.listAreaInfoByCode(storeDTO.stream().map(StoreInfoDTO::getProvinceCode).distinct().collect(Collectors.toList()));
        Map<String, String> provinceInfo = provinceAreaDTOS.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName));
        List<AreaDTO> cityAreaDTOS = baseDataFacade.listAreaInfoByCode(storeDTO.stream().map(StoreInfoDTO::getCityCode).distinct().collect(Collectors.toList()));
        Map<String, String> cityInfo = cityAreaDTOS.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName));
        List<AreaDTO> countyAreaDTOS = baseDataFacade.listAreaInfoByCode(storeDTO.stream().map(StoreInfoDTO::getAreaCode).distinct().collect(Collectors.toList()));
        Map<String, String> countyInfo = countyAreaDTOS.stream().collect(Collectors.toMap(AreaDTO::getCode, AreaDTO::getName));
        storeDTO.forEach(item -> {
            item.setProvinceName(provinceInfo.get(item.getProvinceCode()));
            item.setCityName(cityInfo.get(item.getCityCode()));
            item.setAreaName(countyInfo.get(item.getAreaCode()));
        });
        return storeDTO.stream().collect(Collectors.toMap(StoreInfoDTO::getCode, item -> item));
    }
}
